// Copyright 2012 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package dfa.axis.v1_19;

import com.google.api.ads.dfa.axis.factory.DfaServices;
import com.google.api.ads.dfa.axis.v1_19.Advertiser;
import com.google.api.ads.dfa.axis.v1_19.AdvertiserRecordSet;
import com.google.api.ads.dfa.axis.v1_19.AdvertiserRemote;
import com.google.api.ads.dfa.axis.v1_19.AdvertiserSearchCriteria;
import com.google.api.ads.dfa.lib.client.DfaSession;
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.auth.oauth2.CredentialRefreshListener;
import com.google.api.client.auth.oauth2.TokenErrorResponse;
import com.google.api.client.auth.oauth2.TokenResponse;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeTokenRequest;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.common.collect.Lists;

import java.io.BufferedReader;
import java.io.InputStreamReader;

/**
* This example demonstrates how to authenticate using OAuth2.  This example
* is meant to be run from the command line and requires user input.
*
* @author Joseph DiLallo
*/
public class OAuth2Example {

  private static final String SCOPE = "https://www.googleapis.com/auth/dfatrafficking";

  // This callback URL will allow you to copy the token from the success screen.
  private static final String CALLBACK_URL = "urn:ietf:wg:oauth:2.0:oob";

  // If you do not have a client ID or secret, please create one in the
  // API console: https://code.google.com/apis/console#access
  private static final String CLIENT_ID = "INSERT_CLIENT_ID_HERE";
  private static final String CLIENT_SECRET = "INSERT_CLIENT_SECRET_HERE";

  // Select which DFA User Profile linked to your Google Account will be used
  // for these requests.
  private static final String DFA_USER_PROFILE_NAME = "INSERT_DFA_USER_PROFILE_NAME_HERE";

  private static Credential getOAuth2Credential() throws Exception {
   GoogleAuthorizationCodeFlow authorizationFlow = new GoogleAuthorizationCodeFlow.Builder(
       new NetHttpTransport(),
       new JacksonFactory(),
       CLIENT_ID,
       CLIENT_SECRET,
       Lists.newArrayList(SCOPE))
       .setApprovalPrompt("force")
       // Set the access type to offline so that the token can be refreshed.
       // By default, the library will automatically refresh tokens when it
       // can, but this can be turned off by setting
       // dfa.api.refreshOAuth2Token=false in your ads.properties file.
       .setAccessType("offline").build();

   String authorizeUrl =
       authorizationFlow.newAuthorizationUrl().setRedirectUri(CALLBACK_URL).build();
   System.out.println("Paste this url in your browser: \n" + authorizeUrl + '\n');

   // Wait for the authorization code.
   System.out.println("Type the code you received here: ");
   String authorizationCode = new BufferedReader(new InputStreamReader(System.in)).readLine();

   // Authorize the OAuth2 token.
   GoogleAuthorizationCodeTokenRequest tokenRequest =
       authorizationFlow.newTokenRequest(authorizationCode);
   tokenRequest.setRedirectUri(CALLBACK_URL);
   GoogleTokenResponse tokenResponse = tokenRequest.execute();

   // Create the OAuth2 credential with custom refresh listener.
   GoogleCredential credential = new GoogleCredential.Builder()
       .setTransport(new NetHttpTransport())
       .setJsonFactory(new JacksonFactory())
       .setClientSecrets(CLIENT_ID, CLIENT_SECRET)
       .addRefreshListener(new CredentialRefreshListener() {
         public void onTokenResponse(Credential credential, TokenResponse tokenResponse) {
           // Handle success.
           System.out.println("Credential was refreshed successfully.");
         }

         public void onTokenErrorResponse(Credential credential,
             TokenErrorResponse tokenErrorResponse) {
           // Handle error.
           System.err.println("Credential was not refreshed successfully. "
               + "Redirect to error page or login screen.");
         }
       })

       // You can also add a credential store listener to have credentials
       // stored automatically.
       //.addRefreshListener(new CredentialStoreRefreshListener(userId, credentialStore))
       .build();

   // Set authorized credentials.
   credential.setFromTokenResponse(tokenResponse);

   // Though not necessary when first created, you can manually refresh the
   // token, which is needed after 60 minutes.
   credential.refreshToken();

   return credential;
  }

  public static void main(String[] args) throws Exception {
   if (CLIENT_ID.equals("INSERT_CLIENT_ID_HERE")
       || CLIENT_SECRET.equals("INSERT_CLIENT_SECRET_HERE")) {
     throw new IllegalArgumentException("Please input your client IDs or secret. "
         + "See https://code.google.com/apis/console#access");
   } else if (DFA_USER_PROFILE_NAME.equals("INSERT_DFA_USER_PROFILE_NAME_HERE")) {
     throw new IllegalArgumentException("Please input your DFA User Profile name.");
   }

   // Get the OAuth2 credential.
   Credential credential = getOAuth2Credential();

   // Construct a DfaSession.
   DfaSession session = new DfaSession.Builder()
       .withUsernameAndOAuth2Credential(DFA_USER_PROFILE_NAME, credential)
       .withEnvironment(DfaSession.Environment.PRODUCTION)
       .build();

   DfaServices dfaServices = new DfaServices();

   runExample(dfaServices, session);
}

  public static void runExample(DfaServices dfaServices, DfaSession session) throws Exception {
    // Request the advertiser service from the service client factory.
    AdvertiserRemote advertiserService = dfaServices.get(session, AdvertiserRemote.class);

    // Create advertiser search criteria structure.
    AdvertiserSearchCriteria advSearchCriteria = new AdvertiserSearchCriteria();
    advSearchCriteria.setPageSize(100);
    // When paging, start counting page numbers from 1 rather than 0.
    advSearchCriteria.setPageNumber(1);

    AdvertiserRecordSet advertiserRecordSet;
    int i = 1;

    do {
      // Get advertisers by criteria.
      advertiserRecordSet = advertiserService.getAdvertisers(
          advSearchCriteria);

      for (Advertiser result : advertiserRecordSet.getRecords()) {
        System.out.printf("%s) Advertiser with name \"%s\", ID \"%s\", and spotlight " +
            "configuration ID \"%s\" was found.%n", i++, result.getName(), result.getId(),
            result.getSpotId());
      }

      advSearchCriteria.setPageNumber(advSearchCriteria.getPageNumber() + 1);
    } while (advSearchCriteria.getPageNumber() <= advertiserRecordSet.getTotalNumberOfPages());

    System.out.printf("Number of results found: %s%n",
        advertiserRecordSet.getTotalNumberOfRecords());
  }
}
